import { getBaseUrl, getUploadUrl } from "@/utils/env";

const HTTP_REQUEST_URL = getBaseUrl();
const HTTP_UPLOAD_URL = getUploadUrl();

import { useTokenStore } from "@/store";
// 从pina中读取 token 用于封装上传图片请求头
const tokenStore = useTokenStore();
const token = tokenStore.token;
/**
 * 小程序头像获取上传
 * @param uploadUrl 上传接口地址
 * @param filePath 上传文件路径
 * @param successCallback success回调
 * @param errorCallback err回调
 */
export function uploadImgs(
  uploadUrl: string,
  filePath: string,
  successCallback: Function,
  errorCallback: Function
) {
  uni.uploadFile({
    url: HTTP_REQUEST_URL + uploadUrl,
    filePath: filePath,
    name: "file",
    header: {
      "api-token": token,
      "api-name": "wxapp",
      "Content-Type": "application/x-www-form-urlencoded",
    },
    success: (res) => {
      if (res.statusCode == 403) {
        Tips({
          title: res.data,
        });
      } else {
        let data = res.data ? JSON.parse(res.data) : {};
        if (data.code == 1) {
          successCallback && successCallback(data);
        } else {
          errorCallback && errorCallback(data);
          Tips({
            title: data.msg,
          });
        }
      }
    },
    fail: (err) => {
      Tips({
        title: `上传图片失败`,
      });
    },
    complete: () => {
      uni.hideLoading();
    },
  });
}

/**
 * 获取image图片地址，代替require
 *
 * @param {string} path
 */
export function getImageUrl(name: string) {
  return new URL(`../static/image/${name}.png`, import.meta.url).href;
}
/**
 * 跳转路径封装函数
 * @param url 跳转路径
 */
// 一级页面路径
const tabPage = [
  "/pages/tabbar/home",
  "/pages/tabbar/information",
  "/pages/tabbar/my",
];
export function JumpPath(url: string) {
  let arr = url.split("@APPID=");
  if (arr.length > 1) {
    //#ifdef MP
    uni.navigateToMiniProgram({
      appId: arr[arr.length - 1],
      path: arr[0],
      envVersion: "release",
      success: (res) => {
        console.log("打开成功", res);
      },
      fail: (err) => {},
    });
    //#endif
    //#ifndef MP
    Tips({
      title: "h5与app端不支持跳转外部小程序",
    });
    //#endif
  } else {
    if (url.indexOf("http") != -1) {
      uni.navigateTo({
        url: `/pages/annex/web_view/index?url=${url}`,
      });
    } else {
      if (tabPage.indexOf(url) == -1) {
        uni.navigateTo({
          url,
        });
      } else {
        uni.switchTab({
          url,
        });
      }
    }
  }
}

/**
 * @param opt  object | string
 * @param to_url object | string
 * 例:
 * this.Tips('/pages/test/test'); 跳转不提示
 * this.Tips({title:'提示'},'/pages/test/test'); 提示并跳转
 * this.Tips({title:'提示'},{tab:1,url:'/pages/index/index'}); 提示并跳转值table上
 * tab=1 一定时间后跳转至 tabbar上
 * tab=2 一定时间后跳转至非 tabbar上
 * tab=3 一定时间后返回上页面
 * tab=4 关闭所有页面，打开到应用内的某个页面
 * tab=5 关闭当前页面，跳转到应用内的某个页面
 */
interface TipsOptions {
  title?: string;
  icon?: string;
  endtime?: number;
  success?: () => void;
}
interface ToUrlConfig {
  url?: string;
  type?: string;
  tab?: number;
}
export function Tips(
  opt: TipsOptions | string,
  to_url?: ToUrlConfig | string | Function | Object
): void {
  if (typeof opt == "string") {
    to_url = opt;
    opt = {};
  }
  let title = opt.title || "",
    icon = opt.icon || "none",
    endtime = opt.endtime || 2000,
    success = opt.success;
  if (title)
    uni.showToast({
      title: title,
      icon: [
        "success",
        "loading",
        "none",
        "error",
        "fail",
        "exception",
      ].includes(icon)
        ? (icon as
            | "success"
            | "none"
            | "loading"
            | "error"
            | "fail"
            | "exception")
        : "none",
      duration: endtime,
      success,
    });
  if (to_url != undefined) {
    if (typeof to_url == "object") {
      let tab = to_url.tab || 1,
        url = to_url.url || "";
      switch (tab) {
        case 1:
          //一定时间后跳转至 table
          setTimeout(function () {
            uni.switchTab({
              url: url,
            });
          }, endtime);
          break;
        case 2:
          //跳转至非table页面
          setTimeout(function () {
            uni.navigateTo({
              url: url,
            });
          }, endtime);
          break;
        case 3:
          //返回上页面
          setTimeout(function () {
            // #ifndef H5
            uni.navigateBack({
              delta: parseInt(url),
            });
            // #endif
            // #ifdef H5
            history.back();
            // #endif
          }, endtime);
          break;
        case 4:
          //关闭所有页面，打开到应用内的某个页面
          setTimeout(function () {
            uni.reLaunch({
              url: url,
            });
          }, endtime);
          break;
        case 5:
          //关闭当前页面，跳转到应用内的某个页面
          setTimeout(function () {
            uni.redirectTo({
              url: url,
            });
          }, endtime);
          break;
      }
    } else if (typeof to_url == "function") {
      setTimeout(function () {
        to_url && to_url();
      }, endtime);
    } else {
      //没有提示时跳转不延迟
      setTimeout(
        function () {
          uni.navigateTo({
            url: to_url,
          });
        },
        title ? endtime : 0
      );
    }
  }
}

/*
 * 单图上传
 * @param object opt
 * @param callable successCallback 成功执行方法 data
 * @param callable errorCallback 失败执行方法
 */
interface UploadImageOptions {
  url?: string;
  name?: string;
  count?: number;
  sizeType?: string[];
  sourceType?: string[];
  is_load?: boolean;
  //限定 fileType 类型
  fileType?: "image" | "video" | "audio";
}
export function uploadImageOne(
  opt: UploadImageOptions | string,
  successCallback: Function,
  errorCallback: Function
) {
  if (typeof opt === "string") {
    let url = opt;
    opt = {};
    opt.url = url;
  }
  let count = opt.count || 1,
    sizeType = opt.sizeType || ["compressed"],
    sourceType = opt.sourceType || ["album", "camera"],
    is_load = opt.is_load || true,
    uploadUrl = opt.url || HTTP_UPLOAD_URL,
    inputName = opt.name || "file",
    fileType = opt.fileType || "image";
  uni.chooseImage({
    count: count, //最多可以选择的图片总数
    sizeType: sizeType, // 可以指定是原图还是压缩图，默认二者都有
    sourceType: sourceType, // 可以指定来源是相册还是相机，默认二者都有
    success: function (res) {
      //启动上传等待中...
      uni.showLoading({
        title: "图片上传中",
      });
      uni.uploadFile({
        url: HTTP_REQUEST_URL + uploadUrl,
        filePath: res.tempFilePaths[0],
        fileType: fileType,
        name: inputName,
        formData: {
          filename: inputName,
          server: 1,
        },
        header: {
          // #ifdef MP
          "Content-Type": "application/form-data",
          // #endif
          "api-token": token,
          "api-name": "wxapp",
        },
        success: function (res) {
          uni.hideLoading();
          if (res.statusCode == 403) {
            Tips({
              title: res.data,
            });
          } else {
            let data = res.data ? JSON.parse(res.data) : {};
            if (data.code == 1) {
              successCallback && successCallback(data);
            } else {
              errorCallback && errorCallback(data);
              Tips({
                title: data.msg,
              });
            }
          }
        },
        fail: function (res) {
          uni.hideLoading();
          Tips({
            title: "上传图片失败",
          });
        },
      });
    },
  });
}
/*
 * 多图上传
 * @param object opt
 * @param callable successCallback 成功执行方法 data
 * @param callable errorCallback 失败执行方法
 */
export function uploadImageTwo(
  opt: UploadImageOptions | string,
  successCallback: Function,
  errorCallback: Function
) {
  if (typeof opt === "string") {
    let url = opt;
    opt = {};
    opt.url = url;
  }
  let count = opt.count || 2,
    sizeType = opt.sizeType || ["compressed"],
    sourceType = opt.sourceType || ["album", "camera"];

  uni.chooseImage({
    count: count, //最多可以选择的图片总数
    sizeType: sizeType, // 可以指定是原图还是压缩图，默认二者都有
    sourceType: sourceType, // 可以指定来源是相册还是相机，默认二者都有
    success(res) {
      //启动上传等待中...
      uni.showLoading({
        title: "图片上传中",
      });
      // 明确 tempFilePaths 是字符串数组
      const filePaths: string[] = Array.isArray(res.tempFilePaths)
        ? res.tempFilePaths
        : [res.tempFilePaths];
      uploadFileFun(opt, filePaths, successCallback, errorCallback);
    },
  });
}
interface UploadFileOptions {
  url?: string;
  name?: string;
  count?: number;
  sizeType?: string[];
  sourceType?: string[];
  is_load?: boolean;
  //限定 fileType 类型
  fileType?: "image" | "video" | "audio";
  // 其他可能需要的字段...
}
function uploadFileFun(
  opt: UploadFileOptions,
  arr: string[],
  successCallback: Function,
  errorCallback: Function
) {
  let is_load = opt.is_load || true,
    uploadUrl = opt.url || HTTP_UPLOAD_URL,
    inputName = opt.name || "file",
    fileType = opt.fileType || "image";
  arr.forEach((item) => {
    uni.uploadFile({
      url: HTTP_REQUEST_URL + uploadUrl,
      filePath: item,
      fileType: fileType,
      name: inputName,
      formData: {
        filename: inputName,
        server: 1,
      },
      header: {
        // #ifdef MP
        "Content-Type": "application/form-data",
        // #endif
        "api-token": token,
        "api-name": "wxapp",
      },
      success: function (res) {
        uni.hideLoading();
        if (res.statusCode == 403) {
          Tips({
            title: res.data,
          });
        } else {
          let data = res.data ? JSON.parse(res.data) : {};
          if (data.code == 1) {
            successCallback && successCallback(data);
          } else {
            errorCallback && errorCallback(data);
            Tips({
              title: data.msg,
            });
          }
        }
      },
      fail: function (res) {
        uni.hideLoading();
        Tips({
          title: "上传图片失败",
        });
      },
    });
  });
}
/**
 * 预览图片
 * @param array url 预览的图片数组
 * @param number index 当前预览的图片索引，默认为0
 */
export function previewImageFun(urls: string[], current = 0) {
  if (!urls.length) {
    Tips({
      title: "预览图片失败：缺少有效的图片地址",
    });
    return;
  }
  uni.previewImage({
    urls,
    current,
    fail(err) {
      Tips({
        title: "图片加载失败",
      });
    },
  });
}
/**
 * 检测富文本是否含有图片，并将图片宽高分别设置为100%，auto
 * @param string data 富文本
 * @return string
 */
export function setRichData(data: string) {
  return data.replace(/<img/g, "<img style='width:100%;height:auto;'");
}
/**
 * 打开地图
 *
 */
interface showMaoLocationOptions {
  lat: string;
  lng: string;
  name?: string;
  address?: string;
}
export function showMaoLocation(
  data: showMaoLocationOptions,
  successCallback: Function
) {
  let { lat, lng, name, address } = data;
  if (!lat || !lng)
    return Tips({
      title: `缺少经纬度信息无法查看地图`,
    });
  uni.openLocation({
    latitude: parseFloat(lat),
    longitude: parseFloat(lng),
    scale: 8,
    name: name || "",
    address: address || "",
    success: function (data) {
      successCallback && successCallback(data);
    },
  });
}
/**
 * 腾讯地图逆解析地址，传入经纬度，返回地址信息
 * @param {string} lat lng 经纬度
 * @return {object} 地址信息
 * @return {string} 腾讯地址key值
 */
export function getAdress(
  lat: string,
  lng: string,
  key = "HMQBZ-XC7KD-WZ64J-PFOQM-CFMT6-HUBOX"
) {
  return new Promise((resolve, reject) => {
    uni.request({
      url:
        `https://apis.map.qq.com/ws/geocoder/v1/?key=${key}&location=` +
        lat +
        "," +
        lng,
      success(res) {
        return resolve(res);
      },
      fail(err) {
        return reject(err);
      },
    });
  });
}
const $h = {
  //除法函数，用来得到精确的除法结果
  //说明：javascript的除法结果会有误差，在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
  //调用：$h.Div(arg1,arg2)
  //返回值：arg1除以arg2的精确结果
  Div: function (arg1: any, arg2: any) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var t1 = 0,
      t2 = 0,
      r1,
      r2;
    try {
      t1 = arg1.toString().split(".")[1].length;
    } catch (e) {}
    try {
      t2 = arg2.toString().split(".")[1].length;
    } catch (e) {}
    r1 = Number(arg1.toString().replace(".", ""));
    r2 = Number(arg2.toString().replace(".", ""));
    return this.Mul(r1 / r2, Math.pow(10, t2 - t1));
  },
  //加法函数，用来得到精确的加法结果
  //说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
  //调用：$h.Add(arg1,arg2)
  //返回值：arg1加上arg2的精确结果
  Add: function (arg1: any, arg2: any) {
    arg2 = parseFloat(arg2);
    var r1, r2, m;
    try {
      r1 = arg1.toString().split(".")[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split(".")[1].length;
    } catch (e) {
      r2 = 0;
    }
    m = Math.pow(100, Math.max(r1, r2));
    return (this.Mul(arg1, m) + this.Mul(arg2, m)) / m;
  },
  //减法函数，用来得到精确的减法结果
  //说明：javascript的加法结果会有误差，在两个浮点数相加的时候会比较明显。这个函数返回较为精确的减法结果。
  //调用：$h.Sub(arg1,arg2)
  //返回值：arg1减去arg2的精确结果
  Sub: function (arg1: any, arg2: any) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var r1, r2, m, n;
    try {
      r1 = arg1.toString().split(".")[1].length;
    } catch (e) {
      r1 = 0;
    }
    try {
      r2 = arg2.toString().split(".")[1].length;
    } catch (e) {
      r2 = 0;
    }
    m = Math.pow(10, Math.max(r1, r2));
    //动态控制精度长度
    n = r1 >= r2 ? r1 : r2;
    return ((this.Mul(arg1, m) - this.Mul(arg2, m)) / m).toFixed(n);
  },
  //乘法函数，用来得到精确的乘法结果
  //说明：javascript的乘法结果会有误差，在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
  //调用：$h.Mul(arg1,arg2)
  //返回值：arg1乘以arg2的精确结果
  Mul: function (arg1: any, arg2: any) {
    arg1 = parseFloat(arg1);
    arg2 = parseFloat(arg2);
    var m = 0,
      s1 = arg1.toString(),
      s2 = arg2.toString();
    try {
      m += s1.split(".")[1].length;
    } catch (e) {}
    try {
      m += s2.split(".")[1].length;
    } catch (e) {}
    return (
      (Number(s1.replace(".", "")) * Number(s2.replace(".", ""))) /
      Math.pow(10, m)
    );
  },
};
export { $h };
// 获取地理位置;
const $L = {
  async getLocation() {
    console.log(111111);

    let status: number;
    // #ifdef APP-PLUS
    status = await this.checkPermission();
    if (status !== 1) {
      return;
    }
    // #endif
    // #ifdef MP-WEIXIN || MP-TOUTIAO || MP-QQ
    status = (await this.getSetting()) as number;

    if (status === 2) {
      this.openSetting();
      return;
    }
    // #endif

    return this.doGetLocation();
  },
  doGetLocation() {
    return new Promise((resolve, reject) => {
      uni.getLocation({
        success: (res) => {
          uni.removeStorageSync("CACHE_LONGITUDE");
          uni.removeStorageSync("CACHE_LATITUDE");
          uni.setStorageSync("CACHE_LONGITUDE", res.longitude);
          uni.setStorageSync("CACHE_LATITUDE", res.latitude);
          resolve({ longitude: res.longitude, latitude: res.latitude });
        },
        fail: (err) => {
          // #ifdef MP-BAIDU
          if (err.errCode === 202 || err.errCode === 10003) {
            // 202模拟器 10003真机 user deny
            this.openSetting();
          }
          // #endif
          // #ifndef MP-BAIDU
          if (err.errMsg.indexOf("auth deny") >= 0) {
            uni.showToast({
              title: `访问位置被拒绝`,
            });
          } else {
            uni.showToast({
              title: err.errMsg,
            });
          }
          // #endif
        },
      });
    });
  },
  getSetting: function () {
    return new Promise((resolve, reject) => {
      uni.getSetting({
        success: (res) => {
          if (res.authSetting["scope.userLocation"] === undefined) {
            resolve(0);
            return;
          }
          if (res.authSetting["scope.userLocation"]) {
            resolve(1);
          } else {
            resolve(2);
          }
        },
        fail: (err) => {
          console.log(err, "获取设置失败");
        },
      });
    });
  },
  openSetting: function () {
    uni.openSetting({
      success: (res) => {
        if (res.authSetting && res.authSetting["scope.userLocation"]) {
          this.doGetLocation();
        }
      },
      fail: (err) => {},
    });
  },
  async checkPermission() {
    let status = permision.isIOS
      ? await permision.requestIOS("location")
      : await permision.requestAndroid(
          "android.permission.ACCESS_FINE_LOCATION"
        );

    if (status === null || status === 1) {
      status = 1;
    } else if (status === 2) {
      uni.showModal({
        content: `系统定位已关闭`,
        confirmText: `确定`,
        showCancel: false,
        success: function (res) {},
      });
    } else if (status.code) {
      uni.showModal({
        content: status.message,
      });
    } else {
      uni.showModal({
        content: `需要定位权限`,
        confirmText: `确定`,
        success: function (res) {
          if (res.confirm) {
            permision.gotoAppSetting();
          }
        },
      });
    }
    return status;
  },
};
export { $L };
